//
//  ViewController.m
//  RetainCount
//
//  Created by liuxiang on 2017/11/30.
//  Copyright © 2017年 liuxiang. All rights reserved.
//
//                .-~~~~~~~~~-._       _.-~~~~~~~~~-.
//            __.'              ~.   .~              `.__
//          .'//                  \./                  \\`.
//        .'//                     |                     \\`.
//      .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
//    .'//.-"                 `-.  |  .-'                 "-.\\`.
//  .'//______.============-..   \ | /   ..-============.______\\`.
//.'______________________________\|/______________________________`.




#import "ViewController.h"
#import "User.h"
#import <objc/runtime.h>
#import "UIImage+hhh.h"
#import "UIImage+MC_RGB.h"
#import <WebKit/WebKit.h>

typedef int(^myBlock)(int);

myBlock _block;

int abcd = 10;

static int cdef = 10;

// 函数指针
typedef void(*p)(int);

@interface ViewController () <UITableViewDelegate,UITableViewDataSource>

@property (nonatomic, strong) User *user;

@property (strong, nonatomic) NSMutableArray<User *> *users;

@property (weak, nonatomic) IBOutlet UITableView *tableView;

@property (strong, nonatomic) myBlock block2;



@end

@implementation ViewController



- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    /*
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     NSMutableString *str = [[NSMutableString alloc] initWithString:@"12312"];
     
     NSLog(@"str retainCount = %zi",[str retainCount]);
     NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:str,str, nil];
     NSLog(@"str retainCount = %zi",[str retainCount]);
     [str release];
     NSArray *arr = [[NSArray alloc] initWithObjects:str,dict, nil];
     NSLog(@"str retainCount = %zi",[str retainCount]);
     [str release];
     NSMutableArray *array = [[NSMutableArray alloc] initWithArray:arr];
     NSLog(@"str retainCount = %zi",[str retainCount]);
     
     NSLog(@"dict =%@", dict);
     NSLog(@"strarray =%@", arr);
     NSLog(@"strmarray =%@", array);
     [str appendString:@"0987"];
     NSLog(@"strarray =%@", arr);
     NSLog(@"strmarray =%@", array);
     NSLog(@"dict =%@", dict);
     [dict release];
     [arr release];
     NSLog(@"str retainCount = %zi",[str retainCount]);
     //    [array release];
     //    [str release];
     [pool drain];
     */
    self.navigationItem.title = @"哈哈哈😄";
    
    NSArray<NSDictionary *> *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"1" ofType:@"plist"]];
    NSMutableArray<User *> *users = [NSMutableArray arrayWithCapacity:array.count];
    for (NSDictionary *dict in array) {
        @autoreleasepool{
            User *user = [[User alloc] initWithDict:dict];
            [users addObject:user];
        }
    }
    self.users = users;
    User *u = users.firstObject;
    self.user = u;
    
    NSString *str = @"sss";
    self.user.name = str;
    self.user.name = @"12";
    //    dc,dc,taylor,super,@"", 数组中的每个字段调用valueForKey，添加到数组中返回
    NSArray *valueArray = [array valueForKey:@"name"];
    //    12,dc,taylor,super,<null>, 数组的每个对象分别调用valueForKey，返回结果集
    NSArray *userValueArray = [users valueForKey:@"name"];
    
    // block
    __block int abc = 0;
    
    myBlock tempBlock = ^(int a) {
        //NSMallocBlock,已经复制到堆中
        return a*a + abc;
    };
    
    tempBlock(5);
    
    
    _block = ^(int b){
    // NSGlobalBlock
//        return b+b;
        
        //NSMallocBlock,因为调用了外部__block修饰的变量,拷贝到堆上
        return abc * b;
    };
    _block(5);
    NSLog(@"class = %@",[_block class]);
    
    self.block2 = ^int(int c) {
//        NSGlobalBlock
        return (c+c)*abcd;
    };
    self.block2(5);
    
    //函数指针赋值
    p p = printfnum;
    //直接定义一个函数指针并赋值
    void(*p1)(int) = printfnum;
    NSLog(@"Method = %p",(Method)printfnum);
    NSLog(@"imp = %p",(IMP)printfnum);
    NSLog(@"sel = %p",sel_registerName("printfnum"));
    NSLog(@"function point = %p",p1);
    NSLog(@"function point = %p",p);
    p(10);
    p1(20);
    // 函数指针的定一个和调用与block十分类似，不同的是 * 和 ^
    
    //    [self addProperity:[User class]];
    
    [self addClass];
    [self replaceMethods];
    
    //        [self getProperities:self.user];
    //    User *us = [User new];
    //    [self getProperities:us];

}

// 获取属性列表
- (void) getProperities:(User *)user {
    u_int count = 0;
    objc_property_t *properties = class_copyPropertyList([user class], &count);
    for (int i = 0; i < count; i++) {
        @autoreleasepool{
            const char *propertyName = property_getName(properties[i]);
            const char *attributes = property_getAttributes(properties[i]);
            NSString *str = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
            NSString *attributesStr = [NSString stringWithCString:attributes encoding:NSUTF8StringEncoding];
            NSLog(@"propertyName : %@", str);
            NSLog(@"attributesStr : %@", attributesStr);
            NSString *propertyNameValue = [user valueForKey:str];
            
            NSLog(@"propertyNameValue : %@", propertyNameValue);
        }
    }
}

// 添加属性
- (void) addProperity:(Class)class{
    //    T@"NSArray",&,N,V_array
    
    //    const char * _Nonnull name;           /**< The name of the attribute */
    //    const char * _Nonnull value;
    /*
     unsigned int attributeCount = 0;
     NSMutableString *nameString = [NSMutableString stringWithString:@"T"];
     [nameString appendString:@"@"];
     [nameString appendString:@"\""];
     [nameString appendFormat:@"%@",type];
     [nameString appendString:@"\""];
     
     if ([type isEqualToString:@"NSString"]) {
     // Copy
     [nameString appendString:@",C"];
     }else {
     // Strong/retain
     [nameString appendString:@",&"];
     }
     attributeCount += 1;
     // nonatomic
     [nameString appendString:@",N"];
     attributeCount += 1;
     [nameString appendFormat:@",_%@",name];
     const char *attr_name = nameString.UTF8String;
     const char *attr_value = @"".UTF8String;
     const objc_property_attribute_t *attr = &(objc_property_attribute_t){attr_name,attr_value};
     BOOL addResult = class_addProperty([obj class], name.UTF8String, attr, attributeCount);
     NSLog(@"添加结果 = <%d>",addResult);
     */
    
    objc_property_attribute_t type = { "T", "@\"NSString\"" };
    
    objc_property_attribute_t ownership = { "C", "" }; // C = copy
    
    objc_property_attribute_t nonatomic = { "N", "" }; // N = nonatomic
    
    objc_property_attribute_t backingivar = { "V", [NSString stringWithFormat:@"_%@",@"haha"].UTF8String };
    
    objc_property_attribute_t attrs[] = { type, ownership, nonatomic, backingivar };
    
    BOOL addPresult = class_addProperty(class, "haha", attrs, 4);
    
    class_addIvar(class, "_haha", sizeof(NSString *), 0, "@");
    NSLog(@"addProperty = %d",addPresult);
    // 添加getter方法
    BOOL addgetr = class_addMethod(class, @selector(haha), (IMP)nameGetter, "@@:");
    NSLog(@"addgetr = %d",addgetr);
    
    // 添加set方法
    BOOL addsetr = class_addMethod(class, @selector(setHaha:), (IMP)nameSetter, "v@:@");
    NSLog(@"addsetr = %d",addsetr);
    
    //添加自定义方法
    //    class_addMethod([User class], @selector(myclasstest:), (IMP)myclasstest, "v@:");
    
    
    //    [self getProperities:o];
    
 
}
// 添加类
- (void) addClass {
    Class userA = objc_allocateClassPair([NSObject class], "UserA", 0);
    [self addProperity:userA];
    objc_registerClassPair(userA);
    id obj = [[userA alloc] init];
    [obj setValue:@"hhhhh" forKey:@"haha"];
    NSLog(@"obj haha = %@",[obj valueForKey:@"haha"]);
    [self getProperities:obj];
    
}
// 替换和交换方法
- (void) replaceMethods {
    //    IMP newImp = method_getImplementation(class_getInstanceMethod([User class], @selector(description)));
    // 先替换系统的 description 方法
    class_replaceMethod([User class], @selector(description), (IMP)userDesc, "@@:");
    
    // 将系统的description 和 newDesc方法实现调换
    Method oldDesc = class_getInstanceMethod([User class], @selector(description));
    Method newDesc = class_getInstanceMethod([User class], @selector(newDesc));
    method_exchangeImplementations(oldDesc, newDesc);
    //打印的是 newDesc
    NSLog(@"old desc = %@",self.user.description);
    // 打印的是已经替换过的系统的description方法返回值
    NSLog(@"new desc = %@",self.user.newDesc);
    
    
}

NSString * userDesc(id self, SEL _cmd) {
    NSLog(@"replace methods description");
    return @"sdfsdfsdfds";
}

NSString *nameGetter(id obj, SEL _cmd)

{
    Ivar ivar = class_getInstanceVariable([obj class], "_haha");
    
    return object_getIvar(obj, ivar);
    
}

void nameSetter(id obj, SEL _cmd, NSString *newName)

{
    
    Ivar ivar = class_getInstanceVariable([obj class], "_haha");
    
    id oldName = object_getIvar(obj, ivar);
    
    if (oldName != newName)
        object_setIvar(obj, ivar, [newName copy]);
    
}

static void myclasstest(id obj, SEL _cmd, int a) //self和_cmd是必须的，在之后可以随意添加其他参数
{
    
    Ivar v = class_getInstanceVariable([obj class], "haha");
    //返回名为itest的ivar的变量的值
    id o = object_getIvar(obj, v);
    //成功打印出结果
    NSLog(@"%@", o);
    NSLog(@"int a is %d", a);
}

void printfnum(int a){
    NSLog(@"printfnum = %d",a);
}

#pragma mark -

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellReuserIdentifier = @"cellReuser";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuserIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellReuserIdentifier];
    }
    
    cell.textLabel.text = self.users[indexPath.row].name;
    cell.detailTextLabel.text = self.users[indexPath.row].age.stringValue;
    
    return cell;
}

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.users.count;
}

- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat y = scrollView.contentOffset.y;
    if (y > 0) {
        self.navigationController.navigationBar.alpha = 0;
    }
    self.navigationController.navigationBar.alpha = y/64 > 1?1:y/64;
}


- (IBAction)btnClick:(id)sender {
    NSString *str = @"MCTaylor://dsfsd";
    //    NSString *str = @"www.baidu.com";
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:str]]) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:str] options:@{@"type":@[@"b",@"ajumped"]} completionHandler:^(BOOL success) {
            NSLog(@"success = %d",success);
        }];
    }
}



- (void)dealloc
{
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
